package com.sec.android.app.myfiles.fragment.filelist;

import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MergeCursor;
import android.os.Bundle;
import android.view.View;
import android.widget.ListAdapter;

import com.sec.android.app.myfiles.decorator.AbsAdapterImpDecorator;
import com.sec.android.app.myfiles.fragment.AbsMyFilesFragment;
import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.module.ModuleLoader;
import com.sec.android.app.myfiles.module.abstraction.AbsFileListAdapterImp;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.module.local.foldertree.FolderTreeListAdapterImp;
import com.sec.android.app.myfiles.navigation.NavigationInfo;
import com.sec.android.app.myfiles.operation.FileOperator;
import com.sec.android.app.myfiles.widget.listview.AbsListViewImp;

public class FileListAdapter implements LoaderCallbacks<Cursor> {
    protected AbsFileListAdapterImp mAdapterImp;
    NavigationInfo mCurNavigationInfo;
    Context mContext;

    LoaderManager mLoaderMgr;
    int mLoaderID;
    private boolean mLoadFinished;

    public FileListAdapter(Context context, NavigationInfo navigationInfo, LoaderManager loaderMgr, AbsListViewImp listViewImp) {
        mContext = context.getApplicationContext();
        mLoaderMgr = loaderMgr;

        mCurNavigationInfo = navigationInfo;

        // it needs to be considered as folder or cloud base
        mLoaderID = navigationInfo.getCurRecord().hashCode();
        mAdapterImp = ModuleLoader.getInstance().createAdapterImp(navigationInfo, context, listViewImp);

        try {
            mLoadFinished = true;
            mLoaderMgr.initLoader(mLoaderID, null, this);
        } catch (IllegalStateException e) {
            Log.e(this, "IllegalStateException:" + e.toString());
        }
    }

    public void destroyLoader() {
        if (mLoaderMgr != null) {
            mLoaderMgr.destroyLoader(mLoaderID);
        }
    }

    public AbsFileListAdapterImp getAdapterImp() {
        return mAdapterImp;
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
        if (mAdapterImp == null) {
            return null;
        }
        if (mCurNavigationInfo.needLoadingView()) {
            AbsMyFilesFragment fragment = mCurNavigationInfo.getCurFragment();
            if (mLoadFinished && fragment != null) {
                mAdapterImp.changeCursor(null);
                fragment.setLoadingView();
                mLoadFinished = false;
                if (fragment instanceof FileListFragment) {
                    ((FileListFragment) fragment).notifyOnItemUpdated();
                }
            }
        }
        return new CursorLoader(mContext, mAdapterImp.getUri(), mAdapterImp.getProjection(), mAdapterImp.getSelection(),
                mAdapterImp.getSelectionArgs(), mAdapterImp.getOrderBy());
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        Log.d(this, "onLoadFinished");
        mLoadFinished = true;
        if (data != null) {
            Cursor cursor = data;
            if (mCurNavigationInfo != null && mCurNavigationInfo.isSelectDestination()) {
                cursor = getCreateFolderCursor(data);
            }

            mAdapterImp.changeCursor(cursor);
            if (FileOperator.getFileOperation() == FileOperator.Operation.DELETE && !(mAdapterImp instanceof FolderTreeListAdapterImp)) {
                return;
            }

            mAdapterImp.onLoadFinished(cursor);
        }
    }

    /**
     * Get cursor with Create folder Item
     *
     * @param data
     * @return
     */
    private Cursor getCreateFolderCursor(Cursor data) {
        MatrixCursor matrixCursor;
        Cursor ret = data;
        Object[] createFolderRow = mAdapterImp.getCreateFolderItem();

        if (createFolderRow != null) {
            matrixCursor = new MatrixCursor(mAdapterImp.getProjection());
            matrixCursor.addRow(createFolderRow);

            ret = new MergeCursor(new Cursor[]{matrixCursor, data});
        }

        return ret;
    }

    public boolean getLoadFinished() {
        return mLoadFinished;
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        try {
            mAdapterImp.changeCursor(null);
        } catch (NullPointerException e) {
            Log.e(this, "NullPointerException:" + e.toString());
        }
    }

    public FileRecord getFileRecord(Cursor cursor) {
        return mAdapterImp.getFileRecord(cursor);
    }

    public ListAdapter getAdapter() {
        return mAdapterImp;
    }

    public FileRecord getFileRecord(int position) {
        return mAdapterImp.getFileRecord(position);
    }

    public String getFilePath(int position) {
        return mAdapterImp.getFilePath(position);
    }

    public int getItemCount() {
        return mAdapterImp.getCount();
    }

    public void reload() {
        // mLoaderMgr.destroyLoader(mLoaderID);
        // mLoaderMgr.initLoader(mLoaderID, null, this);
        mLoaderMgr.restartLoader(mLoaderID, null, this);
    }

    public void setCheckMode(boolean bShow, boolean isShare) {
        mAdapterImp.setCheckMode(bShow, isShare);
    }

    public boolean isCheckMode() {
        return (mAdapterImp != null) ? mAdapterImp.isCheckMode() : false;
    }

    public boolean isCheckable(int nPos) {
        return mAdapterImp.isCheckable(nPos);
    }

    public void selectAll(boolean selectAll) {
        mAdapterImp.selectAll(selectAll);
    }

    public void changeContentDescription(View v, boolean isShown) {
        mAdapterImp.changeContentDescription(v, isShown);
    }

    public void clearPreValue() {
        mAdapterImp.clearPreValue();
    }

    public void setDecorator(AbsAdapterImpDecorator decorator) {
        mAdapterImp.setDecorator(decorator);
    }

    public int getDragPosition() {
        return mAdapterImp.getDragPosition();
    }

    public void setDragPosition(int position) {
        mAdapterImp.setDragPosition(position);
    }

    public int getEmptyTextId() {
        return mAdapterImp.getEmptyTextId();
    }

    public int getEmptySubTextId() {
        return mAdapterImp.getEmptySubTextId();
    }

    public int getEmptyIconId() {
        return mAdapterImp.getEmptyIconId();
    }

    public void toggleExpand(int position) {
        mAdapterImp.toggleExpand(position);
    }

    public Cursor getCursor() {
        return mAdapterImp.getCursor();
    }

    public void changeCursor(Cursor cursor) {
        mAdapterImp.changeCursor(cursor);
    }

    public boolean isEnabled(int position) {
        return mAdapterImp.isEnabled(position);
    }

    public int getEmptyTextColor() {
        return mAdapterImp.getEmptyTextColor();
    }
}
